package cn.geminis.workflow.service.configuration;

import cn.geminis.workflow.service.entity.repository.HistoricMapper;
import cn.geminis.workflow.service.service.engine.expression.GeminiExpressionManager;
import cn.geminis.workflow.service.service.engine.listener.ProcessCanceledListener;
import cn.geminis.workflow.service.service.engine.listener.ProcessCompletedListener;
import lombok.RequiredArgsConstructor;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.persistence.StrongUuidGenerator;
import org.flowable.engine.CandidateManager;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.interceptor.CreateUserTaskInterceptor;
import org.flowable.engine.interceptor.StartProcessInstanceInterceptor;
import org.flowable.eventregistry.impl.EventRegistryEngines;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

/**
 * @author puddi
 */
@Configuration
@RequiredArgsConstructor
public class ActivitiConfiguration {

    private final DataSource dataSource;
    private final PlatformTransactionManager transactionManager;
    private final CandidateManager candidateManager;
    private final StartProcessInstanceInterceptor startProcessInstanceInterceptor;
    private final CreateUserTaskInterceptor createUserTaskInterceptor;
    private final ProcessCompletedListener processCompletedListener;
    private final ProcessCanceledListener processCanceledListener;
    private final GeminiExpressionManager expressionManager;

    @Bean
    public SpringProcessEngineConfiguration processEngineConfiguration() {
        EventRegistryEngines.init();

        var configuration = new SpringProcessEngineConfiguration();
        configuration.setDataSource(this.dataSource);
        configuration.setTransactionManager(this.transactionManager);
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        configuration.setCandidateManager(candidateManager);
        configuration.setExpressionManager(expressionManager);
        configuration.setIdGenerator(new StrongUuidGenerator());
        configuration.setStartProcessInstanceInterceptor(this.startProcessInstanceInterceptor);
        configuration.setCreateUserTaskInterceptor(this.createUserTaskInterceptor);

        var customMybatisMappers = new HashSet<Class<?>>();
        customMybatisMappers.add(HistoricMapper.class);
        configuration.setCustomMybatisMappers(customMybatisMappers);

        var listeners = new HashMap<String, List<FlowableEventListener>>(3);
        listeners.put(FlowableEngineEventType.PROCESS_COMPLETED.toString(), List.of(processCompletedListener));
        listeners.put(FlowableEngineEventType.PROCESS_CANCELLED.toString(), List.of(processCanceledListener));
        configuration.setTypedEventListeners(listeners);

        return configuration;
    }

    @Bean
    public ProcessEngine processEngine() {
        return processEngineConfiguration().buildProcessEngine();
    }

}
